package org.airsonic.player.service;

import com.google.common.io.MoreFiles;
import org.apache.commons.configuration2.*;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.sync.ReadWriteSynchronizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class ConfigurationPropertiesService {
    private static final Logger LOG = LoggerFactory.getLogger(ConfigurationPropertiesService.class);

    private final FileBasedConfigurationBuilder<FileBasedConfiguration> builder;

    private final Configuration config;

    public static final String HEADER_COMMENT = "Airsonic preferences.  NOTE: This file is automatically generated."
                           + " Do not modify while application is running";

    private static ConfigurationPropertiesService instance;

    public static ConfigurationPropertiesService getInstance() {
        if (instance == null) {
            reset();
        }
        return instance;
    }

    public static void reset() {
        instance = new ConfigurationPropertiesService();
    }

    private ConfigurationPropertiesService() {
        Path propertyFile = SettingsService.getPropertyFile();
        if (!Files.exists(propertyFile)) {
            try {
                MoreFiles.touch(propertyFile);
            } catch (IOException e) {
                throw new RuntimeException("Could not create new property file", e);
            }
        }
        Parameters params = new Parameters();
        PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout();
        layout.setHeaderComment(HEADER_COMMENT);
        layout.setGlobalSeparator("=");
        builder = new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class).configure(
                params.properties()
                      .setFile(propertyFile.toFile())
                      .setSynchronizer(new ReadWriteSynchronizer())
                      .setLayout(layout));
        try {
            config = builder.getConfiguration();
        } catch (ConfigurationException e) {
            throw new RuntimeException("Could not load property file at " + propertyFile, e);
        }
    }

    public void save() {
        try {
            builder.save();
        } catch (ConfigurationException e) {
            LOG.error("Unable to write to property file.", e);
        }
    }

    public boolean containsKey(String key) {
        return config.containsKey(key);
    }

    public void clearProperty(String key) {
        config.clearProperty(key);
    }

    public void setProperty(String key, Object value) {
        config.setProperty(key, value);
    }

    public Object getProperty(String key) {
        return config.getProperty(key);
    }

    public Configuration getConfiguration() {
        return config;
    }
}
